---
sidebar_position: 1
---
import StickyRight from '../../src/demos/stickyRight'
import Options from '../../src/demos/options'

# Props

## value / onChange

Used to control the data of the grid:
```tsx
function App() => {
  const [ data, setData ] = useState([/*...*/])

  return (
    <DataSheetGrid
      value={data}
      onChange={setData}
    />
  )
}
```

### value
> Type: `T[]`

Each element of the array is a row, elements could be anything like strings or objects.

### onChange
> Type: `(newValue: T[], operations: Operation[]) => void`

The first argument is the new value with the updated rows. In most cases this is all you'll need.
This makes it possible to directly use the state setter:

```tsx
const [ data, setData ] = useState([/*...*/])

return (
  <DataSheetGrid
    value={data}
    onChange={(value) => setData(value)}
  />
)

// This is equivalent to
return (
  <DataSheetGrid
    value={data}
    onChange={setData}
  />
)
```

The second argument is an array of operations:
```ts
type Operation = {
  type: 'UPDATE' | 'DELETE' | 'CREATE'
  fromRowIndex: number
  toRowIndex: number
}
```

In most cases only one operation is passed, but it can happen that multiple operations are batched and passed as second argument.

When `type` is `DELETE`, the row indices refer to the old value, not the one passed as first argument.
`fromRowIndex` is always inclusive, and `toRowIndex` is always exclusive. This means that:
- You can compute the number of impacted rows: `toRowIndex - fromRowIndex`
- You can get the impacted rows: `value.slice(fromRowIndex, toRowIndex)`

You can read [this recipe](../examples/tracking-rows-changes) to have an example.

## Columns
### columns
> Type: `Column[]`

An array of columns. [More details](columns)
```tsx
function App() => {
  return (
    <DataSheetGrid
      columns={[ { title: 'A' }, { title: 'B' }, /*...*/ ]}
    />
  )
}
```

### gutterColumn
> Type: `Column | false`

Used to customize the gutter column to the left of the grid. Mostly used to customize the width or the component that renders the gutter.

To change the width of the gutter column you can simply specify the `basis` key ([More details](columns#basis)):
```tsx
function App() => {
  return (
    <DataSheetGrid gutterColumn={{ basis: 60 }} />
  )
}
```

You can also disable the gutter completely by passing `false`.

### stickyRightColumn
> Type: `Column`<br />
> Default: `null`

Used to add a column to the right of the grid. The added column is sticky (always visible even when scrolling) and
cannot be selected, it is only used to show options to the user: delete row, insert row...

<StickyRight />

```tsx
<DataSheetGrid
  stickyRightColumn={{
    component: ({ deleteRow }) => (
      <button onClick={deleteRow}>❌</button>
    ),
  }}
/>
```

## Size
```tsx
<DataSheetGrid
  height={500}
  rowHeight={30}
  headerRowHeight={50}
/>
```

### height
> Type: `number`<br />
> Default: `400`

Maximum height of the grid in pixels. If the content is longer, the grid becomes scrollable.

### rowHeight
> Type: `number`<br />
> Default: `40`

Height of a single row in pixels. All rows have the same height.

### headerRowHeight
> Type: `number`<br />
> Default: `rowHeight`

Height of the header row in pixels. Passing the value `0` will completely hide the header row.



## Options
<Options />

### lockRows
> Type: `boolean`<br />
> Default: `false`

When true, prevents the user from adding or removing rows, even when using keyboard shortcuts or when pasting large data-set.

### autoAddRow
> Type: `boolean`<br />
> Default: `false`

When true, a new row is added at the end of the grid when the user presses enter while editing a cell from the last row.
`autoAddRow` is useless when `lockRows` is `true`.

### disableContextMenu
> Type: `boolean`<br />
> Default: `false`

When true, no context menu is shown when right clicking. `disableContextMenu` is automatically set to `true` when
`lockRows` is `true`.

### disableExpandSelection
> Type: `boolean`<br />
> Default: `false`

When true, the user will not be able to drag the corner of the selection to expand it.

### disableSmartDelete
> Type: `boolean`<br />
> Default: `false`

When false, deleting an empty cell will select the whole row, and deleting an empty cell of an empty row will actually remove the row from the sheet. Second behaviour is auto-disabled if the lockRows option is enabled.

## Style
### className
> Type: `string`

CSS class of the outer `<div />`.

### style
> Type: `CSSProperties`

Style of the outer `<div />`.

### rowClassName
> Type: `string | ((opt: { rowData: T; rowIndex: number }) => string | undefined)`

CSS class of a row, or a function that returns a CSS class for a given row.

### cellClassName
> Type: `string | ((opt: { rowData: unknown; rowIndex: number, columnId?: string }) => string | undefined)`

CSS class of a cell, or a function that returns a CSS class for a given cell.
This is exactly the same as specifying it [on the column](./columns#cellclassname), but `rowData` is of type `unknown` because we cannot know how the column wraps the value.

## Row behavior
### rowKey
> Type: `string | (({ rowData: T; rowIndex: number }) => string)`<br />
> Default: `({ rowIndex }) => rowIndex`

By default, rows use the row index as the `key`, this is not ideal when inserting / deleting rows in the middle of the grid:
React will update all rows instead of adding / deleting a single one in the middle.
For better performance and to avoid tricky behaviors, it is recommended to use some unique id for each row.

You can specify a `string` that should be a key of the row object `<DataSheetGrid value={[{ id: 'foo' }, ...]} rowKey="id" />`.

For more complex cases (nested properties, compound primary keys, non object rows...) you may specify a function
that take the row object and row index as parameters.

### createRow
> Type: `() => any`<br />
> Default: `() => ({})`

A function that should return a new row object. This function is called once per row every time the user appends
or inserts new rows. Most often used to add default values and / or random ids to new rows.

### duplicateRow
> Type: `({ rowData: T, rowIndex: number }) => any`<br />
> Default: `({ rowData }) => ({ ...rowData })`

A function that should return a new row object from an existing row. This function is called once per row every time the user duplicates rows. Most often used to override values and / or change uniq ids when duplicating rows.

## Customizable components
### addRowsComponent
> Type: `FC<AddRowsComponentProps> | false`

Used to replace the content of the "Add row" button below the grid. Most often used for translations,
custom inputs,
icons...

Passing `false` will hide the component.

See more [details and examples](../i18n#add-button).

### contextMenuComponent
> Type: `FC<ContextMenuComponentProps>`

Used to customize the context menu when right-clicking. 

See more [details and examples](../i18n#context-menu).

## Callbacks
Callbacks receive parameters of type `Cell`. `row` is the index of the row, `col` the index of the column, and `colId`
is the [`id`](columns#id) of the column if specified.

### onFocus
> Type: `({ cell: { colId?: string, col: number, row: number } }) => void`<br />
> Default: `void`

Called when a cell gains focus (ie. the user starts editing its content). This is not the same as active / highlighted.

:::note
To know if the grid itself is focused, you can rely on `onActiveCellChange`.
:::

### onBlur
> Type: `({ cell: { colId?: string, col: number, row: number } }) => void`<br />
> Default: `void`

Called when a cell is blurred (ie. the user stops editing its content).

### onActiveCellChange
> Type: `({ cell: { colId?: string, col: number, row: number } | null }) => void`<br />
> Default: `void`

Called when the active / highlighted cell changes. Called with null when the grid is blurred.

### onSelectionChange
> Type: `({ selection: { min: Cell, max: Cell } | null }) => void`<br />
> Default: `void`

Called when the selection changes. Called with null when the grid is blurred.
